from Config.myConstant import *
from Config.myConfig import *
from DataPrepare.tickFactors.factorBase import factorBase
from DataAccess.TickDataProcess import TickDataProcess
import pandas as pd
import numpy as np
import math
class midPricediffChange(factorBase):
    """描述盘口状态的因子"""
    #----------------------------------------------------------------------
    def __init__(self):
        #super(buySellVolumeRatio,self).__init__()
        super().__init__()
        self.factor='midPricediffChange'
        pass
    #----------------------------------------------------------------------
    def getFactorFromLocalFile(self,code,date):
        mydata=super().getFromLocalFile(code,date,'midPriceChange')
        return mydata
        pass
    #----------------------------------------------------------------------
    def updateFactor(self,code,date,data=pd.DataFrame()):
        exists=super().checkLocalFile(code,date,self.factor)
        if exists==True:
            logger.info(f'No need to compute! {self.factor} of {code} in {date} exists!')
            pass
        if data.shape[0]==0:
             #data=TickDataProcess().getDataByDateFromLocalFile(code,date)
             data=TickDataProcess().getTickShotDataFromInfluxdbServer(code,date)
        result=self.computerFactor(code,date,data)
        super().updateFactor(code,date,self.factor,result)
    #----------------------------------------------------------------------

    def __midSpeed(self,data,span,period):
        result=data[['tick','midPrice']].copy()
        result['EMAMidPrice']=super().EMA(data['midPrice'],span)
        result['speed']=100*np.round((result['EMAMidPrice']/result['EMAMidPrice'].shift(period)-1),5)/(period/20)
        select=result['speed'].isna()
        result.loc[select,'speed']=0
        return result['speed']
        pass
    #----------------------------------------------------------------------
    def __midPricediff(self,data,span,period):
        result=data[['tick','midPrice']].copy()
        result['diff1'] = 100 * np.round((result['midPrice'] / result['midPrice'].shift(period) - 1), 5) / (period / 20)
        select=result['diff1'].isna()
        result.loc[select,'diff1']=0
        result['midPricediff1'] = super().EMA(result['diff1'], span)
        select = result['midPricediff1'].isna()
        result.loc[select, 'midPricediff1'] = 0
        return result['midPricediff1']

        pass

    def __midPriceSquarediff(self,data,span,period):
        result=data[['tick','midPrice']].copy()
        result['diffsquare1'] = 100 * np.round((result['midPrice']*result['midPrice'] / result['midPrice'].shift(period)*result['midPrice'].shift(period) - 1), 5) / (period / 20)
        select=result['diffsquare1'].isna()
        result.loc[select,'diffsquare1']=0
        result['midPricediffdiffsquare1'] = super().EMA(result['diffsquare1'], span)
        select = result['midPricediffdiffsquare1'].isna()
        result.loc[select, 'midPricediffdiffsquare1'] = 0
        return result['midPricediffdiffsquare1']

        pass
    #----------------------------------------------------------------------
    def __midPricediff2(self,data,span,period):
        result=data[['tick','midPrice']].copy()
        result['diff2'] = 100 * np.round((result['midPrice']-result['midPrice'].shift(1)-result['midPrice'].shift(period)+result['midPrice'].shift(period+1) / result['midPrice'].shift(period+1) - 1), 5) / (period / 20)
        select=result['diff2'].isna()
        result.loc[select,'diff2']=0
        result['midPricediff2'] = super().EMA(result['diff2'], span)
        select = result['midPricediff2'].isna()
        result.loc[select, 'midPricediff2'] = 0
        return result['midPricediff2']
        pass
    #----------------------------------------------------------------------
    def __midPrice_weightdiff(self,data,span,period):
        result=data[['tick','midPrice']].copy()
        result['weightdiff'] = 10000 * np.round((result['midPrice'] / result['midPrice'].shift(1) - 1)*((result['midPrice'].shift(1) / result['midPrice'].shift(2) - 1) ** 0.3), 5) / (period / 20)

        select=result['weightdiff'].isna()
        result.loc[select,'weightdiff']=0
        result['__midPrice_weightdiff'] = super().EMA( result['weightdiff'], span)
        select = result['__midPrice_weightdiff'].isna()
        result.loc[select, '__midPrice_weightdiff'] = 0
        return result['__midPrice_weightdiff']

        pass

    def computerFactor(self,code,date,mydata):
        result=pd.DataFrame()
        if mydata.shape[0]!=0:
            result=mydata[['midPrice','tick']].copy()
            result['midPrice'].fillna(method='ffill',inplace=True)
            #----------------------------------------------------------------------
            #计算mid价格的涨跌

            ##################carl###############################
            result['midPricediff_5_3'] = self.__midPricediff(result, 5, 3)
            result['midPricediff_50_3'] = self.__midPricediff(result, 50, 3)
            result['midPricediff_5_10'] = self.__midPricediff(result, 5, 10)
            result['midPricediff_3_50'] = self.__midPricediff(result, 3, 50)

            result['midPriceSquardiff_5_3'] = self.__midPriceSquarediff(result, 5, 3)
            result['midPriceSquardiff_50_3'] = self.__midPriceSquarediff(result, 50, 3)
            result['midPriceSquardiff_5_10'] = self.__midPriceSquarediff(result, 5, 10)
            result['midPriceSquardiff_3_50'] = self.__midPriceSquarediff(result, 3, 50)

            result['midPricediff_weight_5_3'] = self.__midPrice_weightdiff(result, 5, 3)
            result['midPricediff_weight_50_3'] = self.__midPrice_weightdiff(result, 50, 3)
            result['midPricediff_weight_5_10'] = self.__midPrice_weightdiff(result, 5, 10)
            result['midPricediff_weight_3_50'] = self.__midPrice_weightdiff(result, 3, 50)

            # result['midPricediff2_5_3'] = self.__midPricediff2(result, 5, 3)
            # result['midPricediff2_50_3'] = self.__midPricediff2(result, 50, 3)
            # result['midPricediff2_5_10'] = self.__midPricediff2(result, 5, 10)
            # result['midPricediff2_3_50'] = self.__midPricediff2(result, 3, 50)

            openPrice = mydata['lastPrice'].iloc[0]
            if (openPrice == 0):
                openPrice = mydata['midPrice'].iloc[0]

            result['midPriceinter']=(result['midPrice']-openPrice)/openPrice
            result['midPrice_intergral_abs60'] = result['midPriceinter'].rolling(60, min_periods=1).apply(lambda x: np.sum(np.abs(x)))
            result['midPrice_intergral_abs30'] = result['midPriceinter'].rolling(30, min_periods=1).apply(lambda x: np.sum(np.abs(x)))
            result['midPrice_intergral_abs5'] = result['midPriceinter'].rolling(5, min_periods=1).apply(lambda x: np.sum(np.abs(x)))
            result['midPrice_intergral_abs120'] = result['midPriceinter'].rolling(120, min_periods=1).apply(lambda x: np.sum(np.abs(x)))
            result['midPrice_intergral_abs360'] = result['midPriceinter'].rolling(360, min_periods=1).apply(lambda x: np.sum(np.abs(x)))

            result['midPrice_intergral_60'] = result['midPriceinter'].rolling(60, min_periods=1).apply(lambda x: np.sum(x))
            result['midPrice_intergral_30'] = result['midPriceinter'].rolling(30, min_periods=1).apply(lambda x: np.sum(x))
            result['midPrice_intergral_5'] = result['midPriceinter'].rolling(5, min_periods=1).apply(lambda x: np.sum(x))
            result['midPrice_intergral_120'] = result['midPriceinter'].rolling(120, min_periods=1).apply(lambda x: np.sum(x))
            result['midPrice_intergral_360'] = result['midPriceinter'].rolling(360, min_periods=1).apply(lambda x: np.sum(x))

            result['midPriceIncrease']=(result['midPrice']-result['midPrice'].shift(1))/result['midPrice'].shift(1)
            select=result['midPriceIncrease'].isna()==True
            result.loc[select,'midPriceIncrease']=0
            result['maxMidPrice3m']=result['midPrice'].rolling(60,min_periods=1).max()
            result['minMidPrice3m']=result['midPrice'].rolling(60,min_periods=1).min()
            result['differenceHighLow3m']=(result['maxMidPrice3m']-result['minMidPrice3m'])/result['midPrice']
            result['midInPrevious3m']=(result['maxMidPrice3m']-result['midPrice'])/(result['maxMidPrice3m']-result['minMidPrice3m'])
            select=result['maxMidPrice3m']==result['minMidPrice3m']
            result.loc[select,'midInPrevious3m']=0
            #前推前3mMidPrice的波动率
            result['midStd60']=result['midPriceIncrease'].rolling(60,min_periods=1).std()*math.sqrt(14400/3)
            result['midStd60'].fillna(method='ffill',inplace=True)
            select=result['midStd60'].isna()==True
            result.loc[select,'midStd60']=0

        else:
            logger.error(f'There no data of {code} in {date} to computer factor!') 
        return result
    

########################################################################
